package com.chenfan.common.annotations;

import com.chenfan.common.config.Constant;
import com.chenfan.common.extension.context.TraceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.core.MethodParameter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 数据权限编号拦截器
 * @author wulg
 * @date 2024/3/28
 */
@Slf4j
public abstract class DataPrivilegeCodeHandlerInterceptor implements HandlerInterceptor  {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //排除-静态资源handler
        if(handler != null && handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = ((HandlerMethod) handler);
            //排除BasicErrorController
            if (BasicErrorController.class.isAssignableFrom(handlerMethod.getBeanType())) {
                return true;
            }
            //校验数据权限标识
            MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
            if(ArrayUtils.isNotEmpty(methodParameters)) {
                for (MethodParameter methodParameter : methodParameters) {
                    if (!this.hasSearchAuthority(methodParameter)) {
                        continue;
                    }
                    String privilegeCode = request.getHeader(Constant.PRIVILEGE_CODE);
                    if(handlerMethod.hasMethodAnnotation(DataPrivilege.class)) {
                        DataPrivilege dataPrivilege = handlerMethod.getMethodAnnotation(DataPrivilege.class);
                        if(dataPrivilege.ignoreHeader()) {
                            privilegeCode = null;
                        }
                        if(this.isBlank(privilegeCode)) {
                            try {
                                privilegeCode= this.getPrivilegeCode(dataPrivilege.pageComponent());
                                log.info("从权限中心取到的数据权限编号：{}", privilegeCode);
                            } catch (Exception e) {
                                log.error("获取PrivilegeCode失败！", e);
                                throw e;
                            }
                        }
                        if(StringUtils.isNotBlank(privilegeCode)) {
                            TraceContextHolder.put(Constant.PRIVILEGE_CODE, privilegeCode);
                        }
                    }
                    response.addHeader(Constant.PRIVILEGE_CODE, privilegeCode);
                }
            }
        }
        return true;
    }

    public abstract boolean hasSearchAuthority(MethodParameter methodParameter);

    public abstract String getPrivilegeCode(String menuCode);

    private boolean isBlank(String privilegeCode) {
        log.info("从请求头中取到的数据权限编号：{}", privilegeCode);
        if(StringUtils.isBlank(privilegeCode)) {
            return true;
        }
        if(StringUtils.equalsAny(privilegeCode, "null", "undefined")) {
            return true;
        }
        return false;
    }
}
